package com.sun.btrace.cmd;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLClassLoader;

import com.sun.btrace.client.Client;
import com.sun.btrace.comm.ClassPairBody;
import com.sun.btrace.comm.Command;
import com.sun.btrace.comm.ConfCommand;
import com.sun.btrace.comm.ErrorCommand;
import com.sun.btrace.comm.WireIO;
import com.sun.btrace.comm.ConfCommand.OPERATOR;

public class add_class extends CommandCase{

	ClassLoader cl ;
	String targetClassJar ;
	public add_class(){
		cl = null ;
		targetClassJar = null ;
	}
	@Override
	public void help(){
		String help="attach-jar  /home/.../a.jar->/remote/dir/.../a.jar;/home/.../b.jar->/remote/dir/.../b.jar;\n" +
					"Note: \t1. all the class must in one jar"+
					"      \t2. all the class must be loaded or can loaded; that is to say, can't refine new class to jar.";
		context.println(help);
	}
	/**
	 * @param args
	 */
	private  URLClassLoader initClassLoader(String fileList){
		String[] files = fileList.split("\\+;");
        
        URL[] us = new URL[ files.length];
        for( int i=0; i<files.length; ++i){
            try {
                us[i]=new File(files[i]).toURI().toURL();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
         return  new URLClassLoader(us, Thread.currentThread().getContextClassLoader());
    }
	private void test(String c){
		Client.class.getClassLoader().getResource(c.replace(".", "/"));
	}
	/*
	 * attach a.jar->a.jar;b.jar->b.jar
	 * (non-Javadoc)
	 * @see com.sun.btrace.cmd.CommandCase#realCMDAction(java.lang.String[])
	 */
	public void realCMDAction(String...arg){
		String []jars = arg[0].split("\\;+");
		ClassPairBody []cbody = new ClassPairBody[jars.length] ;
		try {
			for (int count = 0; count < jars.length; ++count) {
					String jarL = jars[count].substring(0, jars[count]
							.indexOf("->"));
					String jarR = jars[count].substring(jars[count].indexOf("->")
							+ "->".length());
	
					cbody[count] = new ClassPairBody(jarR,getFileByte(jarL));
				}
			
			ConfCommand cmd = new ConfCommand();
			cmd.setBody(context.getCurrentConfig()) ;
			cmd.setClassBody(cbody);
			cmd.setOperator(OPERATOR.ATTACHJAR) ;

			Socket sock= new Socket(context.getHost(), context.getPort()) ;

			ObjectOutputStream oos = new ObjectOutputStream(sock.getOutputStream());
			ObjectInputStream ois = new ObjectInputStream(sock.getInputStream());
			WireIO.write(oos, cmd);
			Command response = WireIO.read(ois);
			if(response.getType()== Command.SUCCESS){
				context.println("refine class ok.");
				return ;
			}
			if( response.getType()== Command.ERROR){
				context.println("error, detail: " +((ErrorCommand)response).getCause().getMessage());
				((ErrorCommand)response).getCause().printStackTrace(out) ;
				return ;
			}
			else{
				context.println("error happen, but did not get the detail error.") ;
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	public byte[] getFileByte( String jars) throws IOException{
		InputStream in = new FileInputStream(new File(jars));
		byte[] b=input2byte(in);
		if(b==null)
			System.out.println("fail to get resource from " + jars) ;
		return  b;
	}
	public void test(){
		System.out.println("---------->");
	}
	  public static final byte[] input2byte(InputStream inStream)
			throws IOException {
		ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
		byte[] buff = new byte[100];
		int rc = 0;
		while ((rc = inStream.read(buff, 0, 100)) > 0) {
			swapStream.write(buff, 0, rc);
		}
		byte[] in2b = swapStream.toByteArray();
		return in2b;
	} 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		add_class c=new add_class();
		c.cmd("com.sun.btrace.cmd.submit_class");
	}
	private class MyClassLoader extends URLClassLoader{
		public MyClassLoader(URL[] urls) {
			super(urls);
		}

		public   Class<?> defineClassByByte(String name, byte[] b)
		throws ClassFormatError
	    {
		return super.defineClass(name, b, 0,b.length);
	    }
	}
	public String getTargetClassJar() {
		return targetClassJar;
	}
	public void setTargetClassJar(String targetClassJar) {
		this.targetClassJar = targetClassJar;
	}
}
